﻿//    Copyright 2009 Bhavik Shah. (bhavik1st@gmail.com)

//    This file is part of Blobber v 0.1

//    Blobber is free software: you can redistribute it and/or modify it under 
//    the terms of the GNU General Public License as published by the Free Software Foundation,
//    version 3 of the License, or (at your option) any later version.
//    Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
//    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//    See the GNU General Public License for more details.
//    You should have received a copy of the GNU General Public License along with Blobber.
//    If not, see http://www.gnu.org/licenses/.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Configuration;
using System.Collections.Specialized;
using Microsoft.Samples.ServiceHosting.StorageClient; 


namespace Blobber
{
    class Program
    {
        //Min and Max Argument Values for Blobber
        const int minArgCount = 2;
        const int maxArgCount = 4;
        static Boolean bVerbose = false; //Whether application is run in verbose mode.

        //Function which displays Blobber Usage
        static void ShowUsage()
        {
            Console.WriteLine("Blobber 0.1 (c) CopyRight 2009 Bhavik Shah (bhavik1st@gmail.com)");
            Console.WriteLine("Example Usage: ");
            Console.WriteLine("\t\"Blobber -v 1 -u test.txt\" ");
            Console.WriteLine("Argument Options: ");
            Console.WriteLine("\t'-v' <0/1>: Verbosity 0(Off:Default) or 1(On).This argument is optional and should be first if used.");
            Console.WriteLine("\t'-u' or '-d <file>' : Specifies filename to upload or download. \n\tFilename with spaces should be enclosed in \"double quotes\". ");
        }

        //If Verbosity is On put the trace to console.
        static void Verbose(String sTrace)
        {
            if (bVerbose)
            {
                Console.WriteLine("Blobber: {0}", sTrace);
            }
        }

        static void Main(string[] args)
        {
            //1. Count of args is it valid?
            if ((args.Count()%2 == 0) && (args.Count() < minArgCount || args.Count() > maxArgCount))
            {
                Console.WriteLine("Invalid number of Arguments!");
                ShowUsage();
                return;
            }

            String arg;
            for(int iCount=0; iCount < args.Count();iCount++)
            {
                try
                {
                    arg = args[iCount];
                    //2. Syntax of args is it valid?
                    //3. Cases Possible in v0.1
                         //Upload - Get Item from Container
                         //Download - Put Item into Container
                    switch (arg)
                    {
                        case "-v":
                            //Verbosity - 0 Off (Default) 1 on
                            switch (args[iCount + 1])
                            {
                                case "0":
                                    bVerbose = false;
                                    break;
                                case "1":
                                    bVerbose = true;
                                    break;
                                default:
                                    ShowUsage();
                                    return;
                                    //break;
                            }
                            Verbose("Setting Verbosity");
                            iCount++;
                            break;
                        case "-u":
                            //Upload blob file
                            Verbose("Uploading File");
                            if (false == Upload2Blob(args[iCount + 1]))
                            {
                                Console.WriteLine("Error Occured Uploading {0}!!", args[iCount + 1]);
                            }
                            else
                            {
                                Console.WriteLine("File {0} Uploaded Successfully!", args[iCount + 1]);
                            }
                            iCount++;
                            break;
                        case "-d":
                            //Download blob file
                            Verbose("Downloading File");
                            if(false == DownloadFrmBlob(args[iCount + 1]))
                            {
                                Console.WriteLine("Error Occured Downloading {0}!!", args[iCount + 1]);
                            }
                            else
                            {
                                Console.WriteLine("File {0} Downloaded Successfully!",args[iCount + 1]);
                            }
                            iCount++;
                            break;
                        default:
                            Console.WriteLine("Invalid Argument : {0}",arg);
                            break;

                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                    return;
                }

                Console.WriteLine("Blobber 0.1 (c) CopyRight 2009 Bhavik Shah\n");
            }
        }

        //Upload File to Blob
        static bool Upload2Blob(String FileName)
        {
            bool bRetval = true;
            Uri AccessUri = new Uri(ConfigurationSettings.AppSettings["BlobStorageEndpoint"]) ;
            String File = System.IO.Path.GetFileName(FileName);
            String Extension = System.IO.Path.GetExtension(FileName);
            try
            {
                //Create Storage Account Info
                StorageAccountInfo StorageAcc = new StorageAccountInfo(
                    AccessUri,
                    null,
                    (String)ConfigurationSettings.AppSettings["AccountName"],
                    (String)ConfigurationSettings.AppSettings["AccountSharedKey"]);


                // Container names have the same restrictions as DNS names
                BlobStorage blobStorage = BlobStorage.Create(StorageAcc);
                BlobContainer blobContainer = null;
                blobContainer = blobStorage.GetBlobContainer(ConfigurationSettings.AppSettings["ContainerName"]);
                if (false == blobContainer.DoesContainerExist())
                {
                    //Verbose("Container does not exist! Creating One.");
                    blobContainer.CreateContainer(new NameValueCollection(), ContainerAccessControl.Private);
                }

                // Create metadata to be associated with the blob
                NameValueCollection metadata = new NameValueCollection();
                metadata["FileName"] = File;
                metadata["Submitter"] = "Blobber";

                //Create Blob Properties object
                BlobProperties properties = new BlobProperties(File);
                properties.Metadata = metadata;
                properties.ContentType = MimeType(File);

                // Create the blob
                byte [] FileContents = System.IO.File.ReadAllBytes(FileName);
                BlobContents fileBlob = new BlobContents(FileContents);
                blobContainer.CreateBlob(properties, fileBlob, true);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message.ToString());
                bRetval = false;

            }
            return bRetval;
        }

        //Download File From Blob
        static bool DownloadFrmBlob(String FileName)
        {
            bool bRetval = true;
            Uri AccessUri = new Uri(ConfigurationSettings.AppSettings["BlobStorageEndpoint"]) ;
            String Extension = System.IO.Path.GetExtension(FileName);
            String sFile = System.IO.Path.GetFileName(FileName);
            try
            {
                //Create Storage Account Info
                StorageAccountInfo StorageAcc = new StorageAccountInfo(
                    AccessUri,
                    null,
                    (String)ConfigurationSettings.AppSettings["AccountName"],
                    (String)ConfigurationSettings.AppSettings["AccountSharedKey"]);

                // Container names have the same restrictions as DNS names
                BlobStorage blobStorage = BlobStorage.Create(StorageAcc);
                BlobContainer blobContainer = null;
                blobContainer = blobStorage.GetBlobContainer(ConfigurationSettings.AppSettings["ContainerName"]);

                //If Container or Blob Does not exist exception shall be thrown
                FileStream fs = File.Create(FileName);
                BlobContents fileBlob = new BlobContents(fs);
                BlobProperties propBlob;
                propBlob = blobContainer.GetBlob(sFile, fileBlob, true);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
                bRetval = false;
            }

            return bRetval;
        }


        //Get File MimeType from Extension
        static string MimeType(string Filename)
        {
            string mime = "application/octetstream";
            string ext = System.IO.Path.GetExtension(Filename).ToLower();
            Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
            if (rk != null && rk.GetValue("Content Type") != null)
                mime = rk.GetValue("Content Type").ToString();
            return mime;
        }

    }
}
